
import { _decorator, Component, Node, Sprite, Button, sp, ScrollView, Texture2D, Color, Vec2, v2, color, Vec4, v4, instantiate, Label, Toggle, log, Layout, Slider, ToggleContainer, Material, UITransform } from 'cc';
import { AnalyticalParameters } from './AnalyticalParameters';
const { ccclass, property } = _decorator;

/**
 * ps混合叠加模式测试代码
 * Name = PsTools
 * DateTime = Mon Mar 21 2022 23:33:11 GMT+0800 (中国标准时间)
 * Author = 希格斯波色子
 * FileBasename = PsTools.ts
 * FileBasenameNoExtension = PsTools
 * URL = db://assets/psTools/script/PsTools.ts
 * ManualUrl = https://docs.cocos.com/creator/3.4/manual/zh/
 *
 */

export class Vec1 {
    public x:number = 0;
}

export class ToolsLayerOpt {
    name: string = "ToolsLayerOpt";
    constructor(num: number) {
        this.LAYER = {
            active: false,
            num: num,
            activeOpt: {
                UseTexture: {
                    active: false,
                    activeOpt: {
                        texture: null,
                        ScreenCoordinates: {
                            active: false,
                            activeOpt: {

                            },
                            unActiveOpt: {
                                scale: v2(1, 1),
                                offset: v2(0, 0)
                            }
                        }
                    },
                    unActiveOpt: {
                        colorColor: v4(1, 1, 1, 1)
                    }
                },
                BianAn: {
                    active: false
                },
                ZhengPianDieDi: {
                    active: false
                },
                YanSeJiaShen: {
                    active: false
                },
                XianXingJiaShen: {
                    active: false
                },
                BianLiang: {
                    active: false
                },
                LvSe: {
                    active: false
                },
                YanSeJianDan: {
                    active: false
                },
                XianXingJianDan: {
                    active: false
                },
                DieJia: {
                    active: false
                },
                RouGuang: {
                    active: false
                },
                QiangGuang: {
                    active: false
                },
                LiangGuang: {
                    active: false
                },
                XianXingGuang: {
                    active: false
                },
                DianGuang: {
                    active: false
                },
                ShiSeHunHe: {
                    active: false
                },
                ChaZhi: {
                    active: false
                },
                PaiChu: {
                    active: false
                },
                JianQu: {
                    active: false
                },
                HuaFen: {
                    active: false
                },
                SeXiang: {
                    active: false
                },
                BaoHeDu: {
                    active: false
                },
                YanSe: {
                    active: false
                },
                MingDu: {
                    active: false
                }
            },
        }
    }

    LAYER: {
        active: boolean,
        num: number,
        activeOpt: {
            UseTexture: {
                active: boolean,
                activeOpt: {
                    texture: Texture2D,
                    ScreenCoordinates: {
                        active: boolean,
                        activeOpt: {

                        },
                        unActiveOpt: {
                            scale: Vec2,
                            offset: Vec2
                        }
                    }
                },
                unActiveOpt: {
                    colorColor: Vec4
                }
            },
            BianAn: {
                active: boolean
            },
            ZhengPianDieDi: {
                active: boolean
            },
            YanSeJiaShen: {
                active: boolean
            },
            XianXingJiaShen: {
                active: boolean
            },
            BianLiang: {
                active: boolean
            },
            LvSe: {
                active: boolean
            },
            YanSeJianDan: {
                active: boolean
            },
            XianXingJianDan: {
                active: boolean
            },
            DieJia: {
                active: boolean
            },
            RouGuang: {
                active: boolean
            },
            QiangGuang: {
                active: boolean
            },
            LiangGuang: {
                active: boolean
            },
            XianXingGuang: {
                active: boolean
            },
            DianGuang: {
                active: boolean
            },
            ShiSeHunHe: {
                active: boolean
            },
            ChaZhi: {
                active: boolean
            },
            PaiChu: {
                active: boolean
            },
            JianQu: {
                active: boolean
            },
            HuaFen: {
                active: boolean
            },
            SeXiang: {
                active: boolean
            },
            BaoHeDu: {
                active: boolean
            },
            YanSe: {
                active: boolean
            },
            MingDu: {
                active: boolean
            }
        }

    }
};

export class ToolsBrightnessContrast {
    name: string = "ToolsBrightnessContrast";
    constructor(num: number) {
        this.LiangDuDuiBiDu = {
            active: false,
            num: num,
            activeOpt: {
                brightness: new Vec1(),
                constrast: new Vec1()
            }
        }
    }
    LiangDuDuiBiDu: {
        active: boolean,
        num: number,
        activeOpt: {
            brightness: Vec1,
            constrast: Vec1
        }
    }
};

export class ToolsSeXiangBaoHeDuMingDu {
    name: string = "ToolsSeXiangBaoHeDuMingDu";
    constructor(num: number) {
        this.SeXiangBaoHeDuMingDu = {
            active: false,
            num: num,
            activeOpt: {
                u_dH: new Vec1(),
                u_dS: new Vec1(),
                u_dL: new Vec1()
            }
        }
    }
    SeXiangBaoHeDuMingDu: {
        active: boolean,
        num: number,
        activeOpt: {
            u_dH: Vec1,
            u_dS: Vec1,
            u_dL: Vec1
        }
    }
};

//Sprite里面shader的宏定义和参数集
export const spritePsToolsOpt: (ToolsLayerOpt | ToolsBrightnessContrast | ToolsSeXiangBaoHeDuMingDu)[] = [
    new ToolsLayerOpt(1),
    new ToolsLayerOpt(2),
    new ToolsSeXiangBaoHeDuMingDu(1),
    new ToolsLayerOpt(3),
    new ToolsSeXiangBaoHeDuMingDu(2),
    new ToolsBrightnessContrast(1),
    new ToolsBrightnessContrast(2),
    new ToolsLayerOpt(4),
    new ToolsLayerOpt(5)
];

//spine里面shader的宏定义和参数集
export const spinePsToolsOpt: (ToolsLayerOpt | ToolsBrightnessContrast | ToolsSeXiangBaoHeDuMingDu)[] = [
    new ToolsLayerOpt(1),
    new ToolsLayerOpt(2),
    new ToolsSeXiangBaoHeDuMingDu(1),
    new ToolsLayerOpt(3),
    new ToolsSeXiangBaoHeDuMingDu(2),
    new ToolsBrightnessContrast(1),
    new ToolsBrightnessContrast(2),
    new ToolsLayerOpt(4),
    new ToolsLayerOpt(5)
];

//Label里面shader的宏定义和参数集
export const labelPsToolsOpt: (ToolsLayerOpt | ToolsBrightnessContrast | ToolsSeXiangBaoHeDuMingDu)[] = [
    new ToolsLayerOpt(1),
    new ToolsLayerOpt(2),
    new ToolsSeXiangBaoHeDuMingDu(1),
    new ToolsLayerOpt(3),
    new ToolsSeXiangBaoHeDuMingDu(2),
    new ToolsBrightnessContrast(1),
    new ToolsBrightnessContrast(2),
    new ToolsLayerOpt(4),
    new ToolsLayerOpt(5)
];

@ccclass('PsBlendTools')
export class PsBlendTools extends Component {

    @property(Material)
    spriteAndLabelShader:Material = null;
    @property(Material)
    spineShader:Material = null;
    @property(Sprite)
    bgTest: Sprite = null;
    @property(Label)
    labelTest:Label = null;
    @property(sp.Skeleton)
    spineboy: sp.Skeleton = null;
    @property(Button)
    toolsBtn: Button = null;
    @property(Node)
    toolsNode: Node = null;
    @property(ScrollView)
    myScrollView: ScrollView = null;
    @property(Button)
    closeBtn: Button = null;
    @property(Node)
    selectNode: Node = null;
    @property(Node)
    sliderNode: Node = null;
    @property(Node)
    textureNode: Node = null;
    @property(Node)
    sliderItem: Node = null;
    @property(Texture2D)
    tex1:Texture2D = null;
    @property(Texture2D)
    tex2:Texture2D = null;
    @property(Texture2D)
    tex3:Texture2D = null;
    _time: number = 0;
    _open: number = 1;
    _maxTime: number = 5;

    onLoad() {
        this.bgTest.setMaterial(this.spriteAndLabelShader,0);
        this.labelTest.setMaterial(this.spriteAndLabelShader,0);
        this.spineboy.customMaterial = this.spineShader;
        this.toolsNode.active = false;
        this.toolsBtn.node.on("click", () => {
            if (!this.toolsNode.active) {
                this.toolsNode.active = true;
                this.initOpt(spritePsToolsOpt);
            }
        });
        this.closeBtn.node.on("click", () => {
            let shader = new Material();
            let spineShader = new Material();
            AnalyticalParameters.getInstance().analytical([shader],this.spriteAndLabelShader,spritePsToolsOpt);
            AnalyticalParameters.getInstance().analytical([spineShader],this.spineShader,spritePsToolsOpt);
            this._open = 1;
            this._time = 0;
            shader.setProperty("open",this._open);
            spineShader.setProperty("open",this._open);
            this.bgTest.setMaterial(shader,0);
            this.labelTest.setMaterial(shader,0);
            this.spineboy.customMaterial = spineShader;
            this.myScrollView.content.removeAllChildren();
            this.toolsNode.active = false;
        });
        this.selectNode.removeFromParent();
        this.sliderNode.removeFromParent();
        this.sliderItem.removeFromParent();
        this.textureNode.removeFromParent();
    }
    start() {
    }
    public initOpt(optArr: (ToolsLayerOpt | ToolsBrightnessContrast | ToolsSeXiangBaoHeDuMingDu)[]) {
        this.myScrollView.content.removeAllChildren();
        for (let i = 0; i < optArr.length; ++i) {
            if (optArr[i].name == "ToolsLayerOpt") {
                let opt = optArr[i] as ToolsLayerOpt;
                this.addSelectOpt(this.myScrollView.content,opt.LAYER,"LAYER",opt.LAYER.num);
            } else if (optArr[i].name == "ToolsBrightnessContrast") {
                let opt = optArr[i] as ToolsBrightnessContrast;
                this.addSelectOpt(this.myScrollView.content,opt.LiangDuDuiBiDu,"LiangDuDuiBiDu",opt.LiangDuDuiBiDu.num);
            } else if (optArr[i].name == "ToolsSeXiangBaoHeDuMingDu") {
                let opt = optArr[i] as ToolsSeXiangBaoHeDuMingDu;
                this.addSelectOpt(this.myScrollView.content,opt.SeXiangBaoHeDuMingDu,"SeXiangBaoHeDuMingDu",opt.SeXiangBaoHeDuMingDu.num);
            }
        }
    }
    /**
     * 添加选择操作
     * @param selectOpt 
     */
    public addSelectOpt(layout:Node,selectOpt: any,optName:string,num:number) {
        let selectNode = instantiate(this.selectNode);
        selectNode["num"] = num;
        selectNode["info"] = selectOpt;
        let labelNode = selectNode.getChildByName("Label");
        labelNode.getComponent(Label).string = optName + num;
        let toggle = labelNode.getChildByName("Toggle").getComponent(Toggle);
        
        layout.addChild(selectNode);
        if (selectOpt.active) {
            toggle.isChecked = true;
        } else {
            toggle.isChecked = false;
        }
        this.onSelect(toggle);
        toggle.node.on("toggle", this.onSelect, this);
    }
    /**
     * 当选择选项被点击
     * @param toggle 
     */
    public onSelect(toggle: Toggle) {
        let selectNode = toggle.node.parent.parent;
        let layout = selectNode.getChildByName("layout");
        let num = selectNode['num'];
        let info = selectNode['info'];
        info.active = toggle.isChecked;
        layout.removeAllChildren();
        // layout.getComponent(Layout).updateLayout();
        layout.getComponent(UITransform).height = 10;
        if (info.active) {
            //选中
            if ("activeOpt" in info) {
                //对layout增加参数节点
                this.addOptToLayout(layout, info.activeOpt, num);
            }
        } else {
            //不选中
            if ("unActiveOpt" in info) {
                //对layout增加参数节点
                this.addOptToLayout(layout, info.unActiveOpt, num);
            }
        }
    }

    /**
     * 增加参数节点到layout里面
     * @param layout 
     * @param opt 
     * @param num
     */
    public addOptToLayout(layout: Node, opt: any, num: number) {
        for (let keyStr in opt) {
            let info = opt[keyStr];
            switch(keyStr){
                case "u_dH":
                    this.addSliderOpt(layout,info,num,keyStr,180,-180,1);
                    break;
                case "u_dS":
                    this.addSliderOpt(layout,info,num,keyStr,100,-100,1);
                    break;
                case "u_dL":
                    this.addSliderOpt(layout,info,num,keyStr,100,-100,1);
                    break;
                case "brightness":
                    this.addSliderOpt(layout,info,num,keyStr,150,-150,1);
                    break;
                case "constrast":
                    this.addSliderOpt(layout,info,num,keyStr,100,-50,1);
                    break;
                case "scale":
                    this.addSliderOpt(layout,info,num,keyStr,5,0,2);
                    break;
                case "offset":
                    this.addSliderOpt(layout,info,num,keyStr,1,-1,2);
                    break;
                case "colorColor":
                    this.addSliderOpt(layout,info,num,keyStr,1,0,4);
                    break;
                case "texture":
                    this.addTextureOpt(layout,opt,num,keyStr);
                    break;
                default://这是选择选项
                    this.addSelectOpt(layout,info,keyStr,num);
                    break;
            }
            
        }
    }

    public addTextureOpt(layout:Node,opt:any,num:number,name:string){
        let textureNode = instantiate(this.textureNode);
        layout.addChild(textureNode);
        textureNode.getComponent(Label).string = name + num;
        textureNode["opt"] = opt;
        let toggleGroup = textureNode.getChildByName("toggleGroup").getComponent(ToggleContainer);
        if (opt.texture == this.tex1){
            // toggleGroup.notifyToggleCheck(toggleGroup.toggleItems[0]);
            toggleGroup.toggleItems[0].isChecked = true;
            toggleGroup.toggleItems[1].isChecked = false;
            toggleGroup.toggleItems[2].isChecked = false;
        }else if (opt.texture == this.tex2){
            // toggleGroup.notifyToggleCheck(toggleGroup.toggleItems[1]);
            toggleGroup.toggleItems[0].isChecked = false;
            toggleGroup.toggleItems[1].isChecked = true;
            toggleGroup.toggleItems[2].isChecked = false;
        }else if (opt.texture == this.tex3){
            // toggleGroup.notifyToggleCheck(toggleGroup.toggleItems[2]);
            toggleGroup.toggleItems[0].isChecked = false;
            toggleGroup.toggleItems[1].isChecked = false;
            toggleGroup.toggleItems[2].isChecked = true;
        }else{
            opt.texture = this.tex1;
            // toggleGroup.notifyToggleCheck(toggleGroup.toggleItems[0]);
            toggleGroup.toggleItems[0].isChecked = true;
            toggleGroup.toggleItems[1].isChecked = false;
            toggleGroup.toggleItems[2].isChecked = false;
        }
        for(let i = 0;i < toggleGroup.toggleItems.length;++i){
            toggleGroup.toggleItems[i].node.on("toggle",this.onToggleClick,this);
        }
        
    }

    public onToggleClick(toggle:Toggle){
        if (toggle.isChecked){
            if (toggle.node.name == "Toggle1"){
                toggle.node.parent.parent["opt"].texture = this.tex1;
            }else if (toggle.node.name == "Toggle2"){
                toggle.node.parent.parent["opt"].texture = this.tex2;
            }else if (toggle.node.name == "Toggle3"){
                toggle.node.parent.parent["opt"].texture = this.tex3;
            }
        }
    }

    /**
     * 添加滑动操作
     * @param layout 
     * @param opt 
     * @param num 
     * @param name 
     * @param rangeMax 
     * @param rangeMin 
     * @param sliderNum 
     */
    public addSliderOpt(layout:Node,info:any,num:number,name:string,rangeMax:number,rangeMin:number,sliderNum:number){
        let sliderNode = instantiate(this.sliderNode);
        let label = sliderNode.getChildByName("label").getComponent(Label);
        label.string = name + num;
        let rangeL = rangeMax - rangeMin;
        sliderNode["rangeMin"] = rangeMin;
        sliderNode["rangeL"] = rangeL;
        sliderNode["info"] = info;
        if (sliderNum == 1){
            let slider1 = instantiate(this.sliderItem);
            slider1.getComponent(Slider).progress = (info.x - rangeMin)/rangeL;
            slider1.on("slide",this.onSlider,this);
            slider1["vx"] = true;
            slider1.getChildByName("Label").getComponent(Label).string = info.x.toFixed(2);
            sliderNode.addChild(slider1);
        }else if (sliderNum == 2){
            let slider1 = instantiate(this.sliderItem);
            slider1.getComponent(Slider).progress = (info.x - rangeMin)/rangeL;
            slider1.on("slide",this.onSlider,this);
            slider1["vx"] = true;
            slider1.getChildByName("Label").getComponent(Label).string = info.x.toFixed(2);
            sliderNode.addChild(slider1);
            let slider2 = instantiate(this.sliderItem);
            slider2.getComponent(Slider).progress = (info.y - rangeMin)/rangeL;
            slider2.on("slide",this.onSlider,this);
            slider2["vy"] = true;
            slider2.getChildByName("Label").getComponent(Label).string = info.y.toFixed(2);
            sliderNode.addChild(slider2);
        }else if (sliderNum == 4){
            let slider1 = instantiate(this.sliderItem);
            slider1.getComponent(Slider).progress = (info.x - rangeMin)/rangeL;
            slider1.on("slide",this.onSlider,this);
            slider1["vx"] = true;
            slider1.getChildByName("Label").getComponent(Label).string = info.x.toFixed(2);
            sliderNode.addChild(slider1);
            let slider2 = instantiate(this.sliderItem);
            slider2.getComponent(Slider).progress = (info.y - rangeMin)/rangeL;
            slider2.on("slide",this.onSlider,this);
            slider2["vy"] = true;
            slider2.getChildByName("Label").getComponent(Label).string = info.y.toFixed(2);
            sliderNode.addChild(slider2);
            let slider3 = instantiate(this.sliderItem);
            slider3.getComponent(Slider).progress = (info.z - rangeMin)/rangeL;
            slider3.on("slide",this.onSlider,this);
            slider3["vz"] = true;
            slider3.getChildByName("Label").getComponent(Label).string = info.z.toFixed(2);
            sliderNode.addChild(slider3);
            let slider4 = instantiate(this.sliderItem);
            slider4.getComponent(Slider).progress = (info.w - rangeMin)/rangeL;
            slider4.on("slide",this.onSlider,this);
            slider4["vw"] = true;
            slider4.getChildByName("Label").getComponent(Label).string = info.w.toFixed(2);
            sliderNode.addChild(slider4);
        }

        layout.addChild(sliderNode);
    }

    public onSlider(slider:Slider){
        let parentNode = slider.node.parent;
        let rangeMin = parentNode["rangeMin"];
        let rangeL = parentNode["rangeL"];
        let info = parentNode["info"];
        if ("vx" in slider.node){
            info.x = slider.progress * rangeL + rangeMin;
            slider.node.getChildByName("Label").getComponent(Label).string = info.x.toFixed(2);
        }else if ("vy" in slider.node){
            info.y = slider.progress * rangeL + rangeMin;
            slider.node.getChildByName("Label").getComponent(Label).string = info.y.toFixed(2);
        }else if ("vz" in slider.node){
            info.z = slider.progress * rangeL + rangeMin;
            slider.node.getChildByName("Label").getComponent(Label).string = info.z.toFixed(2);
        }else if ("vw" in slider.node){
            info.w = slider.progress * rangeL + rangeMin;
            slider.node.getChildByName("Label").getComponent(Label).string = info.w.toFixed(2);
        }
    }

    update(deltaTime: number) {
        if (this._time > this._maxTime) {
            this._time = 0;
            this._open *= -1;
            this.bgTest.getSharedMaterial(0)?.setProperty("open", this._open);
            let matCaches = this.spineboy['_materialCache'];
            for (var x in matCaches) {
                let m = matCaches[x];
                m.setProperty("open", this._open);
            }
        }
        this._time += deltaTime;
        this.bgTest.getSharedMaterial(0)?.setProperty("time", this._time);
        let matCaches = this.spineboy['_materialCache'];
        for (var x in matCaches) {
            let m = matCaches[x];
            m.setProperty("time", this._time);
        }
    }
}


